package io.web.usercenter.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.web.usercenter.aspect.HasPermission;
import io.web.usercenter.common.BaseResponse;
import io.web.usercenter.common.ErrorCode;
import io.web.usercenter.common.ResultUtils;
import io.web.usercenter.common.validation.group.Add;
import io.web.usercenter.common.validation.group.Edit;
import io.web.usercenter.exception.BusinessException;
import io.web.usercenter.model.domain.User;
import io.web.usercenter.model.domain.request.UploadForm;
import io.web.usercenter.model.domain.request.UserLoginRequest;
import io.web.usercenter.model.domain.request.UserRegisterRequest;
import io.web.usercenter.service.UserService;
import io.web.usercenter.utils.PageWrapper;
import io.web.usercenter.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static io.web.usercenter.contant.UserConstant.ADMIN_ROLE;
import static io.web.usercenter.contant.UserConstant.USER_LOGIN_STATE;

/**
 * 用户接口
 *
 * @author yupi
 */
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Resource
    private UserService userService;

    @PostMapping("/register")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
        String userAccount;
        String userPassword;
        String checkPassword;
        String planetCode;
        if (userRegisterRequest == null || StringUtils.isAnyBlank(
                userAccount = userRegisterRequest.getUsername(),
                userPassword = userRegisterRequest.getPassword(),
                checkPassword = userRegisterRequest.getCheckPassword(),
                planetCode = userRegisterRequest.getPlanetCode())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long result = userService.userRegister(userAccount, userPassword, checkPassword, planetCode);
        return ResultUtils.success(result);
    }

    @PostMapping("/login")
    public BaseResponse<User> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
        String username;
        String password;
        if (userLoginRequest == null || StringUtils.isAnyBlank(
                username = userLoginRequest.getUsername(),
                password = userLoginRequest.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 账户不能包含特殊字符
        String validPattern = "[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Matcher matcher = Pattern.compile(validPattern).matcher(username);
        if (matcher.find()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账户不能包含特殊字符");
        }
        User user = userService.userLogin(username, password, request);
        return ResultUtils.success(user);
    }

    @PostMapping("/logout")
    public BaseResponse<Integer> userLogout(HttpServletRequest request) {
        if (request == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        int result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

    @GetMapping("/getUserInfo")
    public BaseResponse<User> getUserInfo(HttpServletRequest request) {
        String userAgent = request.getHeader("user-agent");
        HttpSession session = request.getSession();
        log.info("Http Session Id = {}, userAgent = {}", session.getId(), userAgent);
        Object userObj = session.getAttribute(USER_LOGIN_STATE);
        User currentUser = (User) userObj;
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        long userId = currentUser.getId();
        // TODO 校验用户是否合法
        User user = userService.getById(userId);
        User safetyUser = userService.getSafetyUser(user);
        return ResultUtils.success(safetyUser);
    }

    @PostMapping("/search")
    @HasPermission
    @ApiResponse(code = 0, message = "", response = User.class)
    public BaseResponse<PageWrapper.PageResponse<User>> searchUsers(@RequestBody UserVo userVo, HttpServletRequest request) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(userVo.getUsername())) {
            queryWrapper.like("username", userVo.getUsername());
        }
        if (StringUtils.isNotBlank(userVo.getUserAccount())) {
            queryWrapper.like("userAccount", userVo.getUserAccount());
        }
        if (Objects.nonNull(userVo.getGender())) {
            queryWrapper.eq("gender", userVo.getGender());
        }
        if (StringUtils.isNotBlank(userVo.getPhone())) {
            queryWrapper.eq("phone", userVo.getPhone());
        }
        if (StringUtils.isNotBlank(userVo.getEmail())) {
            queryWrapper.eq("email", userVo.getEmail());
        }
        if (Objects.nonNull(userVo.getUserStatus())) {
            queryWrapper.eq("userStatus", userVo.getUserStatus());
        }
        if (Objects.nonNull(userVo.getUserRole())) {
            queryWrapper.eq("userRole", userVo.getUserRole());
        }
        PageHelper.startPage(userVo.getPageNo(), userVo.getPageSize());
        PageWrapper.PageResponse<User> pageList = PageWrapper.pageWrapper(userService.list(queryWrapper));
        pageList.getData().forEach(this::desensitizer);
        return ResultUtils.success(pageList);
    }

    @PostMapping("/add")
    @HasPermission
    public BaseResponse<Long> add(@RequestBody @Validated(value = {Add.class}) UserVo userVo, HttpServletRequest request) {
        Long id = userService.add(userVo);
        return ResultUtils.success(id);
    }

    @PostMapping("/edit")
    @HasPermission
    public BaseResponse<Long> edit(@RequestBody @Validated(value = {Edit.class}) UserVo userVo, HttpServletRequest request) {
        userService.edit(userVo);
        return ResultUtils.success(userVo.getId());
    }

    /**
     * 脱敏
     * @param user
     */
    public void desensitizer(User user) {
        user.setUserPassword(null);
    }

    @PostMapping("/deleteByIds")
    @HasPermission
    public BaseResponse<Boolean> deleteByIds(@RequestBody List<Long> ids, HttpServletRequest request) {
        boolean b = userService.removeByIds(ids);
        return ResultUtils.success(b);
    }

    /**
     * 是否为管理员
     *
     * @param request
     * @return
     */
//    private void hasPermission(HttpServletRequest request) {
//        // 仅管理员可查询
//        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
//        User user = (User) userObj;
//        if (user == null || user.getUserRole() != ADMIN_ROLE) {
//            throw new BusinessException(ErrorCode.NO_AUTH);
//        }
//    }
    @ApiOperation(value = "文件素材上传接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "file", value = "文件流对象,接收数组格式", required = true, dataType = "MultipartFile", allowMultiple = true),
            @ApiImplicitParam(name = "title", value = "title", required = true, example = "{\"attachment\":\"\",\"createTime\":\"\",\"doubtId\":\"\",\"doubtTopaperTime\":\"\",\"doubtTopaperUserid\":\"\",\"doubtTopaperUsername\":\"\",\"eviType\":\"\",\"evidenceCode\":\"\",\"evidenceDescription\":\"证据说明\",\"evidenceName\":\"证据名称\",\"extra1\":\"\",\"extra2\":\"\",\"id\":null,\"materialLibraryId\":\"\",\"modifyTime\":\"\",\"snapshotid\":\"\",\"workingFindingId\":\"\",\"workingPaperId\":\"13\"}")}
    )
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse<Long> upload(@RequestPart(name = "file", required = false) MultipartFile[] file, @RequestParam String title) {
        return ResultUtils.success(null);
    }

    // 官方示例
    @Order(value = 3)
    @ApiOperation(value = "多文件MultipartFile上传")
    @ApiImplicitParams({@ApiImplicitParam(name = "file[]", value = "文件流对象,接收数组格式", required = true, dataType = "MultipartFile", allowMultiple = true),
            @ApiImplicitParam(name = "title", value = "title", required = true)}
    )
    @RequestMapping(value = "/uploadMaterial", method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse uploadMaterial(@RequestParam(value = "file[]", required = true) MultipartFile[] files, @RequestParam(value = "title") String title, HttpServletRequest request) throws IOException {
        return ResultUtils.success(null);
    }


    @ApiOperation(value = "文件素材上传接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "file", value = "文件流对象,接收数组格式", required = true, dataType = "MultipartFile", allowMultiple = true),
            @ApiImplicitParam(name = "title", value = "title", required = true, paramType = "form")}
    )
    @RequestMapping(value = "/uploadWithUserJson", method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse<Long> uploadWithUserJson(@RequestPart(name = "file", required = false) MultipartFile[] file, @RequestParam String title) {
        return ResultUtils.success(null);
    }


    @ApiOperation(value = "@ModelAttribute")
    @PostMapping("addByModelAttribute")
    public BaseResponse<Long> addByModelAttribute(@ModelAttribute UploadForm uploadForm) {
        return ResultUtils.success(null);
    }
}
